package com.dau.system.config.rabbit;

import cn.hutool.json.JSONUtil;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

import static com.dau.common.util.RabbitUtil.*;

/**
 * 配置
 *
 * @author tzj
 * @date 2024/11/27
 */
@Configuration
public class RabbitConfig {


    /**
     * 死信交换机
     */
    @Bean
    public DirectExchange delayExchange() {
        return new DirectExchange(DELAY_EXCHANGE_NAME, true, false);
    }

    /**
     * 死信队列
     */
    @Bean
    public Queue delayQueue() {
        Map<String, Object> map = new HashMap<>(3);
        // 设置15分钟过期时间
        map.put("x-message-ttl", 1000);
        map.put("x-dead-letter-exchange", DELAY_RECEIVER_EXCHANGE_NAME);
        map.put("x-dead-letter-routing-key", DELAY_RECEIVER_KEY_NAME);
        return new Queue(DELAY_QUEUE_NAME, true, false, false, map);
    }

    /**
     * 给死信队列绑定交换机
     */
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(DELAY_KEY_NAME);
    }

    /**
     * 死信接收交换机
     */
    @Bean
    public DirectExchange delayReceiveExchange() {
        return new DirectExchange(DELAY_RECEIVER_EXCHANGE_NAME, true, false);
    }

    /**
     * 死信接收队列,用于接收死信，该队列为正常队列，进入该队列的消息会被立即消费
     */
    @Bean
    public Queue delayReceiveQueue() {
        return new Queue(DELAY_RECEIVER_QUEUE_NAME);
    }

    /**
     * 给死信交换机绑定消费队列
     */
    @Bean
    public Binding userOrderReceiveBinding() {
        return BindingBuilder.bind(delayReceiveQueue()).to(delayReceiveExchange()).with(DELAY_RECEIVER_KEY_NAME);
    }

    //绑定键
    public final static String user = "topic.user";
    public final static String order = "topic.order";

    @Bean
    public Queue userQueue() {
        return new Queue(RabbitConfig.user);
    }

    @Bean
    public Queue orderQueue() {
        return new Queue(RabbitConfig.order);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange("topicExchange");
    }


    //将firstQueue和topicExchange绑定,而且绑定的键值为topic.man
    //这样只要是消息携带的路由键是topic.man,才会分发到该队列
    @Bean
    Binding bindingExchangeMessage() {
        return BindingBuilder.bind(userQueue()).to(exchange()).with(user);
    }

    //将orderQueue和topicExchange绑定,而且绑定的键值为用上通配路由键规则topic.#
    // 这样只要是消息携带的路由键是以topic.开头,都会分发到该队列
    @Bean
    Binding bindingExchangeMessage2() {
        return BindingBuilder.bind(orderQueue()).to(exchange()).with("topic.#");
    }


    @Bean
    public Queue NewDirectQueue() {
        // durable:是否持久化,默认是false,持久化队列：会被存储在磁盘上，当消息代理重启时仍然存在，暂存队列：当前连接有效
        // exclusive:默认也是false，只能被当前创建的连接使用，而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除，当没有生产者或者消费者使用此队列，该队列会自动删除。
        //   return new Queue("TestDirectQueue",true,true,false);

        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("NewDirectQueue", true);
    }

    //Direct交换机 起名：NewDirectExchange
    @Bean
    DirectExchange NewDirectExchange() {
        return new DirectExchange("NewDirectExchange", true, false);
    }

    //绑定  将队列和交换机绑定, 并设置用于匹配键：NewDirectRouting
    @Bean
    Binding bindingDirect() {
        return BindingBuilder.bind(NewDirectQueue()).to(NewDirectExchange()).with("NewDirectRouting");
    }

    @Bean
    DirectExchange lonelyDirectExchange() {
        return new DirectExchange("lonelyDirectExchange");
    }


    /**
     * 创建三个队列 ：fanout.A   fanout.B  fanout.C
     * 将三个队列都绑定在交换机 fanoutExchange 上
     * 因为是扇型交换机, 路由键无需配置,配置也不起作用
     */
    @Bean
    public Queue queueA() {
        return new Queue("fanout.A");
    }

    @Bean
    public Queue queueB() {
        return new Queue("fanout.B");
    }

    @Bean
    public Queue queueC() {
        return new Queue("fanout.C");
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA() {
        return BindingBuilder.bind(queueA()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeB() {
        return BindingBuilder.bind(queueB()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeC() {
        return BindingBuilder.bind(queueC()).to(fanoutExchange());
    }

    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
        //设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
        rabbitTemplate.setMandatory(true);

        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            System.out.println("ConfirmCallback:     " + "相关数据：" + JSONUtil.toJsonStr(correlationData));
            System.out.println("ConfirmCallback:     " + "确认情况：" + ack);
            System.out.println("ConfirmCallback:     " + "原因：" + cause);
        });

        rabbitTemplate.setReturnsCallback(returnedMessage -> {
            System.out.println("ReturnCallback:     " + "消息：" + JSONUtil.toJsonStr(returnedMessage.getMessage()));
            System.out.println("ReturnCallback:     " + "回应码：" + returnedMessage.getReplyCode());
            System.out.println("ReturnCallback:     " + "回应信息：" + returnedMessage.getReplyText());
            System.out.println("ReturnCallback:     " + "交换机：" + returnedMessage.getExchange());
            System.out.println("ReturnCallback:     " + "路由键：" + returnedMessage.getRoutingKey());
        });

        return rabbitTemplate;
    }


}
